#include "RTMP.h"

#define RTMP_HEADER_SIZE (RTMP_MAX_HEADER_SIZE + sizeof(RTMPPacket))

RTMPPacket *packet1 = NULL; // SPS+PSS

int RTMP_ConnectNginx(RTMP **r, char *url)
{
	// 创建句柄
	*r = RTMP_Alloc();
	if (r == NULL)
	{
		printf("RTMP_Alloc\n");
		return -1;
	}
	// 初始化句柄
	RTMP_Init(*r);
	// 设置推流地址
	RTMP_SetupURL(*r, url);
	// 开启输出模式
	RTMP_EnableWrite(*r);
	// 连接服务器
	int ret = RTMP_Connect(*r, NULL);
	if (ret == 0)
	{
		printf("RTMP_Connect\n");
		return -1;
	}
	// 连接流
	ret = RTMP_ConnectStream(*r, 0);
	if (ret == 0)
	{
		printf("RTMP_ConnectStream\n");
		return -1;
	}

	return 0;
}

/**********************************************
函数功能：发送H264的数据包
函数参数：r  流媒体句柄
		  h264_buf:H264的裸流数据
		  length：裸流数据的字节大小
		  framtype:帧的类型     1表示关键帧    0表示非关键帧
函数返回值：成功返回0   失败返回-1
**********************************************/
int RTMPSend_H264_Packet(RTMP *r, unsigned char *h264_buf, unsigned int length, int framtype)
{
	// Header+packet+flv的格式头+H264裸流数据
	RTMPPacket *packet = NULL;
	packet = (RTMPPacket *)malloc(RTMP_HEADER_SIZE + length + 9);
	// 指向申请的内存的m_body位置
	packet->m_body = (char *)packet + RTMP_HEADER_SIZE;
	unsigned int timer_ = 1000 / 30; // 相对时间戳步进时间
	static unsigned timer = 0;
	timer += timer_; // 相对时间值
	int i = 0;
	if (framtype == 1)
	{
		// 关键帧
		packet->m_body[i++] = 0x17; // 该帧为关键帧    采用了高级编码
		packet->m_body[i++] = 0x01; // 非SPS  和PPS
		packet->m_body[i++] = 0x00; // 合成时间
		packet->m_body[i++] = 0x00;
		packet->m_body[i++] = 0x00;

		// 裸流的数据长度
		packet->m_body[i++] = (length >> 24) & 0xff;
		packet->m_body[i++] = (length >> 16) & 0xff;
		packet->m_body[i++] = (length >> 8) & 0xff;
		packet->m_body[i++] = (length) & 0xff;

		// 拷贝裸流字节到发送包
		memcpy(&packet->m_body[i], h264_buf, length);

		i += length;

		packet->m_headerType = RTMP_PACKET_SIZE_LARGE; // 使用大容量数据包
		packet->m_packetType = RTMP_PACKET_TYPE_VIDEO; // 组包的是视频
		packet->m_hasAbsTimestamp = 0;				   // 绝对时间戳
		packet->m_nChannel = 0x06;					   // 通道编号
		packet->m_nTimeStamp = timer;				   // 相对时间戳
		packet->m_nInfoField2 = r->m_stream_id;		   // 流id
		packet->m_nBodySize = i;					   // 数据包部分的字节长度
	}
	else
	{
		// 非关键帧
		packet->m_body[i++] = 0x27; // 该帧为关键帧    采用了高级编码
		packet->m_body[i++] = 0x01; // 非SPS  和PPS
		packet->m_body[i++] = 0x00; // 合成时间
		packet->m_body[i++] = 0x00;
		packet->m_body[i++] = 0x00;
		// 裸流的数据长度
		packet->m_body[i++] = (length >> 24) & 0xff;
		packet->m_body[i++] = (length >> 16) & 0xff;
		packet->m_body[i++] = (length >> 8) & 0xff;
		packet->m_body[i++] = (length) & 0xff;
		// 拷贝裸流字节到发送包
		memcpy(&packet->m_body[i], h264_buf, length);
		i += length;
		packet->m_headerType = RTMP_PACKET_SIZE_LARGE; // 使用大容量数据包
		packet->m_packetType = RTMP_PACKET_TYPE_VIDEO; // 组包的是视频
		packet->m_hasAbsTimestamp = 0;				   // 绝对时间戳
		packet->m_nChannel = 0x06;					   // 通道编号
		packet->m_nTimeStamp = timer;				   // 相对时间戳
		packet->m_nInfoField2 = r->m_stream_id;		   // 流id
		packet->m_nBodySize = i;					   // 数据包部分的字节长度
	}
	// 发送RTMP数据包

	RTMP_SendPacket(r, packet, 0);
	// 释放堆内存
	free(packet);
	return 0;
}

/**********************************************
函数功能：发送H264的SPS+PPS数据包
函数参数：r  流媒体句柄
		  sp:  包含sps和pps以及sps_len和pps_len的结构体指针
函数返回值：成功返回0   失败返回-1
**********************************************/
int RTMP_SendSpsPacket(RTMP *r, sps_pps *sp)
{
	// Header+packet+flv的格式头+H264裸流数据
	packet1 = (RTMPPacket *)malloc(RTMP_HEADER_SIZE + 1024);
	if (packet1 == NULL)
	{
		printf("get packet malloc\n");
		return -1;
	}
	// 指向申请的内存的m_body位置
	packet1->m_body = (char *)packet1 + RTMP_HEADER_SIZE;

	int i = 0;
	// 关键帧
	packet1->m_body[i++] = 0x17; // 该帧为关键帧    采用了高级编码
	packet1->m_body[i++] = 0x00; // 是SPS  和PPS数据
	packet1->m_body[i++] = 0x00; // 合成时间
	packet1->m_body[i++] = 0x00;
	packet1->m_body[i++] = 0x00;

	packet1->m_body[i++] = 0x1; // 版本号

	packet1->m_body[i++] = sp->sps[1]; // 配置信息---》宽高
	packet1->m_body[i++] = sp->sps[2]; // 播放器的兼容性
	packet1->m_body[i++] = sp->sps[3];

	packet1->m_body[i++] = 0xff;					  // NAL的长度，值固定为0xff
	packet1->m_body[i++] = 0xe1;					  // SPS的个数
	packet1->m_body[i++] = (sp->sps_len >> 8) & 0xff; // 高8位
	packet1->m_body[i++] = sp->sps_len & 0xff;		  // 低8位

	// sps数据
	memcpy(&packet1->m_body[i], sp->sps, sp->sps_len);
	i += sp->sps_len;

	// PPS个数
	packet1->m_body[i++] = 0x01;
	// PPS长度
	packet1->m_body[i++] = (sp->pps_len >> 8) & 0xff; // 高8位
	packet1->m_body[i++] = sp->pps_len & 0xff;		  // 低8位

	// pps数据
	memcpy(&packet1->m_body[i], sp->pps, sp->pps_len);
	i += sp->pps_len;

	// 配置packet
	packet1->m_headerType = RTMP_PACKET_SIZE_LARGE; // 使用大容量数据包
	packet1->m_packetType = RTMP_PACKET_TYPE_VIDEO; // 组包的是视频
	packet1->m_hasAbsTimestamp = 0;					// 绝对时间戳
	packet1->m_nChannel = 0x06;						// 通道编号
	packet1->m_nTimeStamp = 0;						// 相对时间戳
	packet1->m_nInfoField2 = r->m_stream_id;		// 流id
	packet1->m_nBodySize = i;						// 数据包部分的字节长度

	// 发送SPS+PPS数据包
	RTMP_SendPacket(r, packet1, 0);
	// 释放堆内存
	free(packet1);

	return 0;
}

int RTMP_Release(RTMP *r)
{

	RTMP_Close(r);
	RTMP_Free(r);
}